
#include "SysUtil.h"
#include "StrUtil.h"
#include "FileUtil.h"
#include "CrypUtil.h"

using namespace x2lib;


/*************************************************************************
** Desc		: 函数
** Author	: xktesla@2016-11-18 20:51:07
**************************************************************************/
#if 0
void SysUtil::RedirectIOToConsole()
{
	int hConHandle;
	long lStdHandle;
	CONSOLE_SCREEN_BUFFER_INFO coninfo;
	FILE *fp;

	// 分配一个控制台程序  
	AllocConsole();

	// 设置足够大的屏幕缓存可以让我们滑动文\E6\9C?
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);

	// 设置控制台屏幕的高度
	coninfo.dwSize.Y = 500;

	// 设置控制台屏幕缓存大\E5\B0?
	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

	// 获取标准输出句柄
	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);

	//打开标准输出句柄，类似打开文件的方式如fopen,返回一个文件描述符
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

	// 以可写的方式打开
	fp = _fdopen(hConHandle, "w");

	*stdout = *fp;

	setvbuf(stdout, NULL, _IONBF, 0);

	// redirect unbuffered STDIN to the console  
	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

	fp = _fdopen(hConHandle, "r");
	*stdin = *fp;
	setvbuf(stdin, NULL, _IONBF, 0);

	// redirect unbuffered STDERR to the console  
	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

	fp = _fdopen(hConHandle, "w");
	*stderr = *fp;
	setvbuf(stderr, NULL, _IONBF, 0);

	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog  
	// point to console as well  
	std::ios::sync_with_stdio();
}
#endif

int SysUtil::ReadLine(char buff[], bool mode)
{
	// 阻塞模式
	if (0 == mode)
	{
		int len = 0;
		buff[0] = 0;
		scanf("%[^\n]", buff);
		getchar();
		return strlen(buff);
	}

	// 非阻塞模式
	static char strInput[4096];
	static int idx = 0;
	if (idx > sizeof(strInput))
		return -1;

	int iRet = 0;
	//fflush((&__iob_func()[0]));
	if (!kbhit())
	{
#ifdef __X2LIB_WIN32__
		Sleep(50);
#elif defined __X2LIB_LINUX__
		usleep(50 * 1000);
#endif
		return 0;
	}
	// 另外：win系统可以通过直接*stdin=*fp，来重定向stdin
	char ch = getch();
#ifdef __X2LIB_WIN32__
	putch(ch == '\r' ? '\n' : ch);
#endif
	if (ch == 8)
	{ // 退格键
#ifdef __X2LIB_WIN32__
		putch(' ');
		putch(8);
#elif defined __X2LIB_LINUX__ // xktesla@2018-6-3 00:38:37 coding 无效！未解决linux检测不到退格键的问题
		printf("\b \b");
#endif
		strInput[idx>0 ? (--idx) : 0] = 0;
	}
	else
	{
		strInput[idx++] = ch;
		strInput[idx] = 0;
		if (ch == '\n' || ch == '\r' || ch == EOF)
		{
			strInput[--idx] = 0;
			iRet = idx;
			idx = 0;
			strcpy(buff, strInput);
		}
	}
	return iRet;
}



/*************************************************************************
** Desc     : PrintBlock
** Param    : [io] pBuff 缓冲区
**          : [in] nWindow 窗口宽度
**          : [in] nMaxChars 每行最大字符数
**          : [in] iStartEnd 前后位置偏移
**          : [in] pString 要打印的字符，不能包含换行符
** Return   :
** Author   : xktesla
*************************************************************************/
void PrintBlock(char *pBuff, int nWindow, int nMaxChars, int iStartEnd, const char *pString)
{
	int nString = strlen(pString);
	int rString = (nString / (nMaxChars + 1)) + 1;
	for (int i = 0; i < rString; i++)
	{
		char strFmt[32] = { 0 };
#if 0
		sprintf(strFmt, "%%-%dc", iStartEnd);
		printf(strFmt, '|');
#else
		char szTemp[256] = {0};
		sprintf(szTemp, strFmt, '|');
		strcat(pBuff, szTemp);
#endif
		int cTitle = (i + 1 == rString && nString != nMaxChars) ? (nString % nMaxChars) : nMaxChars;
		for (int j = 0; j < cTitle; j++)
		{
			char chs[2] = {0};
			chs[0] = pString[i*nMaxChars + j];
#if 0
			printf("%s", chs);
#else
			strcat(pBuff,chs);
#endif
		}
#if 0
		for (int x = 0; x < (nWindow - iStartEnd - cTitle - 1); x++) printf(" ");
		printf("|\n");
#else
		for (int x = 0; x < (nWindow - iStartEnd - cTitle - 1); x++) strcat(pBuff," ");
		strcat(pBuff,"|\n");
#endif
	}
}

int SysUtil::PrintW(char *pBuff, const char *pTitle, const char *pContent, const char *pTips, const char *pAppVer, int nWidth) {
	// 原始Title
	int nTitle = strlen(pTitle);

	// 内容宽度最小满足[| x |]，即5个字符
	if (nWidth < 5)
	{
		nWidth = nTitle + 4;
	}

	int nBuff = nWidth * 500; // 最大支持打印500行
	if (pBuff == NULL) return nBuff;
	pBuff[0] = 0;

	const int nMaxTitle = nWidth - 4; // 调整后的窗口内可容纳的最大Title宽
	const int nMaxContent = nMaxTitle; // 调整后的窗口内可容纳的最大Content宽
	const int nMaxAppVer = nMaxTitle; // 调整后的窗口内可容纳的最大AppVer宽

	// 计算Title的起始位置和所需要的行数
	int rTitle = (nTitle / (nMaxTitle + 1)) + 1;
	int iTitle = 2; // 先假设一行容纳不下，所以应该等于2；
	if (nWidth >= nTitle + 4)
	{ // 若一行能够容纳
		iTitle = (nWidth - nTitle) / 2;
	}

	// 计算Content起点
	int iContent = 1;
	// 计算Tips起点
	int iTips = 2;

	// 原始AppVer
	int nAppVer = strlen(pAppVer);
	// 计算AppVer的起始位置和所需要的行数
	int rAppVer = (nAppVer / (nMaxTitle + 1)) + 1;
	int iAppVer = 2; // 先假设一行容纳不下，所以应该等于2；
	if (nWidth >= nAppVer + 4)
	{ // 若一行能够容纳
		iAppVer = (nWidth - nAppVer) / 2;
	}

	//**********依据以上值打印所有***********
	//打印上沿和Title
#if 0
	printf("+");
	for (int i = 0; i<nWidth - 2; i++) printf("=");
	printf("+\n");
#else
	strcat(pBuff, "+");
	for (int i = 0; i<nWidth - 2; i++) strcat(pBuff, "=");
	strcat(pBuff, "+\n");
#endif
	PrintBlock(pBuff, nWidth, nMaxTitle, iTitle, pTitle);

	//打印上沿和Content
#if 0
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
#else
	strcat(pBuff, "|");
	for (int i = 0; i<nWidth - 2; i++) strcat(pBuff, ".");
	strcat(pBuff, "|\n");
#endif
	char szRowColContent[16][128] = { 0 }; // 此设置要求Content最多不能超过16个换行符，且每行最多128个字符

	int nRowContent = StrUtil::Split(pContent, "\n", (char**)szRowColContent);
	for (int i = 0; i < nRowContent; i++) PrintBlock(pBuff, nWidth, nMaxContent, iContent, szRowColContent[i]);

	//打印上沿和Tips
#if 0
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
#else
	strcat(pBuff, "|");
	for (int i = 0; i<nWidth - 2; i++) strcat(pBuff, ".");
	strcat(pBuff, "|\n");
#endif
	char szRowColTips[16][128] = { 0 }; // 此设置要求Content最多不能超过16个换行符，且每行最多128个字符
	int nRowTips = StrUtil::Split(pTips, "\n", (char**)szRowColTips);
	for (int i = 0; i < nRowTips; i++) PrintBlock(pBuff, nWidth, nMaxContent, iTips, szRowColTips[i]);

	//打印上沿和szAppVer
#if 0
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf(".");
	printf("|\n");
#else
	strcat(pBuff, "|");
	for (int i = 0; i<nWidth - 2; i++) strcat(pBuff, ".");
	strcat(pBuff, "|\n");
#endif
	PrintBlock(pBuff, nWidth, nMaxAppVer, iAppVer, pAppVer);

	// 打印下沿
#if 0
	printf("|");
	for (int i = 0; i<nWidth - 2; i++) printf("_");
	printf("|\n");
#else
	strcat(pBuff, "|");
	for (int i = 0; i<nWidth - 2; i++) strcat(pBuff, "_");
	strcat(pBuff, "|\n");
#endif
	return nBuff;
}


char *SysUtil::GetFmtDateTime(char *szDt, int nDt, uint64_t tick, const char *szFmt, bool isUtc)
{
    //time_t time_utc = 0;
    //time_t time_local = 0;

    //struct tm* tm_local = localtime(&time_local);
    //struct tm* tm_utc = gmtime(&time_utc);

    //int time_zone = tm_local->tm_hour - tm_utc->tm_hour;

    time_t tm = tick;
	if (tm == 0) { time(&tm); }

    struct tm* t = nullptr;
    if (isUtc) { t = gmtime(&tm); }
    else { t = localtime(&tm); }
    strftime(szDt, nDt, szFmt, t);
	return szDt;
}

//struct tm {
//	int tm_sec;         /* 秒，范围从 0 到 59                */
//	int tm_min;         /* 分，范围从 0 到 59                */
//	int tm_hour;        /* 小时，范围从 0 到 23                */
//	int tm_mday;        /* 一月中的第几天，范围从 1 到 31                    */
//	int tm_mon;         /* 月份，范围从 0 到 11                */
//	int tm_year;        /* 自 1900 起的年数                */
//	int tm_wday;        /* 一周中的第几天，范围从 0 到 6                */
//	int tm_yday;        /* 一年中的第几天，范围从 0 到 365                    */
//	int tm_isdst;       /* 夏令时                        */
//};
uint32_t SysUtil::GetDateTimeTick(const char *szDt, uint8_t* pWDay, const char* szFmt)
{
	// 获取当前完整时间结构时间
	time_t nowtime;
	time(&nowtime);
	struct tm* sTime = localtime(&nowtime);
	sTime->tm_year += 1900;
	sTime->tm_mon += 1;

    if (szDt != NULL && szDt[0])
    {
        if (0 == strcmp(szFmt, "%Y-%m-%d %H:%M:%S")) sscanf(szDt, "%d-%d-%d %d:%d:%d", &sTime->tm_year, &sTime->tm_mon, &sTime->tm_mday, &sTime->tm_hour, &sTime->tm_min, &sTime->tm_sec);
        else if (0 == strcmp(szFmt, "%Y-%m-%d %H:%M")) sscanf(szDt, "%d-%d-%d %d:%d", &sTime->tm_year, &sTime->tm_mon, &sTime->tm_mday, &sTime->tm_hour, &sTime->tm_min);
        else if (0 == strcmp(szFmt, "%m-%d %H:%M:%S")) sscanf(szDt, "%d-%d %d:%d:%d", &sTime->tm_mon, &sTime->tm_mday, &sTime->tm_hour, &sTime->tm_min, &sTime->tm_sec);
        else if (0 == strcmp(szFmt, "%Y-%m-%d")) sscanf(szDt, "%d-%d-%d", &sTime->tm_year, &sTime->tm_mon, &sTime->tm_mday);
        else if (0 == strcmp(szFmt, "%H:%M:%S")) sscanf(szDt, "%d:%d:%d", &sTime->tm_hour, &sTime->tm_min, &sTime->tm_sec);
        else if (0 == strcmp(szFmt, "%m-%d")) sscanf(szDt, "%d-%d", &sTime->tm_mon, &sTime->tm_mday);
        else if (0 == strcmp(szFmt, "%H:%M")) sscanf(szDt, "%d:%d", &sTime->tm_hour, &sTime->tm_min);
    }

	if (0 == strcmp(szFmt, "%Y-%m-%d %H:%M") || 0 == strcmp(szFmt, "%H:%M")) { sTime->tm_sec = 0; }
	else if (0 == strcmp(szFmt, "%Y-%m-%d") || 0 == strcmp(szFmt, "%m-%d")) { sTime->tm_hour = 0; sTime->tm_min = 0; sTime->tm_sec = 0; }

	sTime->tm_year -= 1900;
	sTime->tm_mon -= 1;
	if (pWDay) { *pWDay = (uint8_t)sTime->tm_wday; }

    // 也可以手动转换
    time_t ft = mktime(sTime); // sTime最小值接受70年-0月-1日 0时：0分：0秒【格林威治[0时区]】，但当前系统时区位东8区，因此最小接受70年-0月-1日 8时：0分：0秒
    return (uint32_t)ft;
}

uint64_t SysUtil::GetCurrentTick(bool isMill)
{
    uint64_t tick;
#ifdef __X2LIB_WIN32__
	tick = ::GetTickCount();
#elif defined __X2LIB_LINUX__
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	tick = (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
#endif 
	return (isMill ? tick : (tick/1000));
}


int SysUtil::Random(int nMax)
{
	static int i = 0;
	if (SysUtil::GetCurrentTick() - i > 1000 * 60)
	{
		i = (int)SysUtil::GetCurrentTick();
		srand(i);
	}
	return rand() % nMax;
}

std::string SysUtil::GenUUID(const unsigned int len)
{
    std::stringstream ss;
    for (uint32_t i = 0; i < len; i++) 
    {
        std::random_device rd;  //获取随机数种子
        std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
        //std::mt19937 gen(std::random_device());
        std::uniform_int_distribution<int> dis(0, 255);
        const int rc = dis(gen);
        std::stringstream hexstream;
        hexstream << std::hex << rc;
        auto hex = hexstream.str();
        ss << (hex.length() < 2 ? '0' + hex : hex);
    }
    return ss.str();
}

int SysUtil::AlignUP(int iCurSize, unsigned int nAlignSize)
{
	if (iCurSize <= 0) return 0;
	if (iCurSize%nAlignSize == 0)return iCurSize;
	return (iCurSize / nAlignSize + 1)*nAlignSize;
}

bool SysUtil::IsOverlap(int addr1, int len1, int addr2, int len2)
{
	if ((addr1 + len1)<addr2 || addr1>(addr2 + len2))
		return false;
	return true;
}


uint8_t* SysUtil::FindBytes(const void *pData, uint32_t nData, void *pFind, uint32_t nFind, int iWhich)
{
	uint8_t *pTemp = NULL;
	uint8_t *p = NULL;
	intz_t nPos = 0;
	intz_t i = 0;
	while (pData && (p = (uint8_t*)memchr((uint8_t*)pData + nPos, ((uint8_t*)pFind)[0], nData - nPos)) && (nPos = (uintz_t)p - (uintz_t)pData + 1) <= (int)(nData - nFind))
	{
		if (0 == memcmp(p, pFind, nFind))
		{
			pTemp = p;
			if (iWhich == ++i) return p;
		}
	}
	if (0 == iWhich)
		return pTemp;
	return NULL;
}

int SysUtil::ReplaceBytes(void *pData, int dataLen, const void *oldArr, const void *newArr, int arrLen)
{
	int iCount = 0;
	int idxFind = -1;
	for (int i = 0; i < dataLen - arrLen + 2; i++)
	{
		for (int j = 0; j<arrLen; j++)
		{
			if (((char*)pData)[i + j] == ((char*)oldArr)[j])
			{
				if (j == arrLen - 1)
				{
					idxFind = i;
					break;
				}
				continue;
			}
			break;
		}
		if (idxFind != -1)
			break;
	}
	if (idxFind != -1)
	{
		iCount++;
#if 0 // 此段代码会被自动编译为memcpy
		for (int i = idxFind; i < idxFind + arrLen; i++)
			pData[i] = newArr[i - idxFind];
#else
		memcpy(&((char*)pData)[idxFind], newArr, arrLen);
#endif
		iCount += ReplaceBytes(&((char*)pData)[idxFind + arrLen], dataLen - idxFind - 1, oldArr, newArr, arrLen);
		//return (iCount + ReplaceBytes(&((char*)pData)[idxFind + arrLen], dataLen - idxFind - 1, oldArr, newArr, arrLen));
	}

	return iCount;
}

bool SysUtil::ReplaceBytes(char *pData, uint32_t nData, const void *oldArr, uint32_t oldLen, const void *newArr, uint32_t newLen, char *pDatanew, uint32_t *pnDatanew, bool isIgnoreCase)
{
	int nDatanew = *pnDatanew;
	*pnDatanew = 0;
	for (uint32_t i = 0; i < nData;)
	{
		int idxFind = -1;
		for (uint32_t j = 0; j<oldLen && (i + j<nData); j++)
		{
			bool isAllow = false;
			if (isIgnoreCase)
			{
				char chs[3] = { pData[i + j], ((char*)oldArr)[j], 0 };
				StrUtil::ToLower(chs, NULL);
				isAllow = (chs[0] == chs[1]);
			}

			if (isAllow || (pData[i + j] == ((char*)oldArr)[j]))
			{
				if (j == oldLen - 1)
				{
					idxFind = i;
					break;
				}
				continue;
			}
			break;
		}
		if (idxFind == -1)
		{
			pDatanew[*pnDatanew] = pData[i];
			(*pnDatanew)++;
			i++;
		}
		else
		{
			int x = nDatanew - (*pnDatanew);
			x = x > newLen ? newLen : x;
			if (x <= 0)
			{
				return false;
			}
			memcpy(&pDatanew[*pnDatanew], newArr, x);
			(*pnDatanew) += x;
			i += oldLen;
		}
	}

	return true;
}


//void SysUtil::ReplaceBytes(void *pDataAddr, void *newArr, int arrLen)
//{
//	for (int i = 0; i < arrLen; i++)
//		((char*)pDataAddr)[i] = ((char*)newArr)[i];
//}

const char* SysUtil::GetWorkDir(uint8_t mode, char* buff, uint32_t bufflen)
{
	static char szWorkDir[1024];

	char* pszDir = szWorkDir;
	uint32_t nDir = sizeof(szWorkDir);
	if (buff) 
	{
		pszDir = buff;
		nDir = bufflen;
	}

#ifdef __X2LIB_WIN32__
	if (!GetModuleFileNameA(NULL, pszDir, nDir))
		return nullptr;
#elif defined __X2LIB_LINUX__
#if 0
	getcwd(pszDir, nDir);
#else
	int rslt = readlink("/proc/self/exe", pszDir, nDir);
	if (rslt < 0)
		return nullptr;
	pszDir[rslt] = 0;
#endif
#endif
	char* p = strrchr(pszDir, '\\');
	if (p == nullptr) { p = strrchr(pszDir, '/'); }

	if (p)
	{
		if (1 == mode)
		{
			*(p + 1) = 0;
		}
		else if (2 == 0)
		{
			strcpy(pszDir, p + 1);
		}
	}

	return pszDir;
}


bool SysUtil::IsZero(float fVal)
{
	const double EPSINON = 1e-6;
	return ((fVal >= -EPSINON) && (fVal <= EPSINON));
}

bool SysUtil::IsZero(double dVal)
{
	const double EPSINON = 1e-15;
	return ((dVal >= -EPSINON) && (dVal <= EPSINON));
}

int SysUtil::CompareVer(const char* pszVer1, const char* pszVer2)
{
	char* pStrs1[128] = { 0 };
	char* pStrs2[128] = { 0 };
	int nStrs1 = StrUtil::Split(pszVer1, ".", pStrs1);
	int nStrs2 = StrUtil::Split(pszVer2, ".", pStrs2);

	if (nStrs1 > nStrs2) { return 1; }
	else if (nStrs1 < nStrs2) { return -1; }

	for (int i = 0;i < nStrs1;++i)
	{
		int num1 = StrUtil::Str2Int(pStrs1[i]);
		int num2 = StrUtil::Str2Int(pStrs2[i]);
		if (num1 > num2) { return 1; }
		else if (num1 < num2) { return -1; }
	}

	return 0;
}

uint8_t HEA[] = "\x61\xFB\x32\x53\x20\x22\x02\x03";
uint8_t SEG = '\x0C'; // 换页符
uint8_t TAI[] = "\x61\xFB\x32\x53\x20\x22\x02\x04";
bool SysUtil::SetAppVer(const char* pszFile, const char* pszVerNum, const char* pszVerTips)
{
	CrypUtil::Encrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Encrypt(TAI, TAI, sizeof(TAI), 0x5A);
	bool isSucc = false;
	const int nLen1 = strlen(pszVerNum) + 1;
	const int nLen2 = strlen(pszVerTips) + 1;
	const int nMore = sizeof(HEA) + nLen1 + sizeof(SEG) + nLen2 + sizeof(TAI);
	const int nData = FileUtil::GetFileSize(pszFile);
	char* pData = (char*)calloc(1, nData + nMore);
	do
	{
		if (!FileUtil::ReadWrite(pszFile, pData, nData, true)) { break; }

		int index = nData;
		memcpy(&pData[index], HEA, sizeof(HEA));
		index += sizeof(HEA);
		memcpy(&pData[index], pszVerNum, nLen1);
		index += nLen1;
		memcpy(&pData[index], &SEG, sizeof(SEG));
		index += sizeof(SEG);
		memcpy(&pData[index], pszVerTips, nLen2);
		index += nLen2;
		memcpy(&pData[index], TAI, sizeof(TAI));
		isSucc = FileUtil::ReadWrite(pszFile, pData, nData + nMore, false);
	} while (false);

	free(pData);
	CrypUtil::Decrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Decrypt(TAI, TAI, sizeof(TAI), 0x5A);
	return isSucc;
}
const char* SysUtil::GetAppVer(const char* pszFile, char szTips[256])
{
	static char szVerNum[16] = { 0 };

	if (pszFile == nullptr)
	{
		char szFileName[512] = { 0 };
#ifdef __X2LIB_WIN32__
		::GetModuleFileNameA(NULL, szFileName, sizeof(szFileName));
#else
		//获取当前程序绝对路径
		readlink("/proc/self/exe", szFileName, sizeof(szFileName));
#endif
		pszFile = szFileName;
	}

	CrypUtil::Encrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Encrypt(TAI, TAI, sizeof(TAI), 0x5A);
	szVerNum[0] = 0;
	const int nData = FileUtil::GetFileSize(pszFile);
	char* pData = (char*)calloc(1, nData);
	if (FileUtil::ReadWrite(pszFile, pData, nData, true))
	{
		char* pHea = (char*)MemStrX(pData, (void*)HEA, nData, sizeof(HEA));
		if (pHea)
		{
			char* pTai = (char*)MemStrX(pHea, (void*)TAI, nData, sizeof(TAI));
			if (pTai)
			{
				char* pVer = pHea + sizeof(HEA);
				strcpy(szVerNum, pVer);
				char* pSeg = (char*)MemStrX(pVer, (void*)&SEG, (pTai - pVer), sizeof(SEG));
				if (pSeg && szTips)
				{
					strcpy(szTips, pSeg + sizeof(SEG));
				}
			}
		}
	}
	free(pData);
	CrypUtil::Decrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Decrypt(TAI, TAI, sizeof(TAI), 0x5A);
	return szVerNum;
}
bool SysUtil::DelAppVer(const char* pszFile)
{
	static char szVerNum[16] = { 0 };

	bool isSucc = true;
	if (pszFile == nullptr)
	{
		char szFileName[512] = { 0 };
#ifdef __X2LIB_WIN32__
		::GetModuleFileNameA(NULL, szFileName, sizeof(szFileName));
#else
		//获取当前程序绝对路径
		readlink("/proc/self/exe", szFileName, sizeof(szFileName));
#endif
		pszFile = szFileName;
	}

	CrypUtil::Encrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Encrypt(TAI, TAI, sizeof(TAI), 0x5A);
	szVerNum[0] = 0;
	const int nData = FileUtil::GetFileSize(pszFile);
	char* pData = (char*)calloc(1, nData);
	if (FileUtil::ReadWrite(pszFile, pData, nData, true))
	{
		char* pHea = (char*)MemStrX(pData, (void*)HEA, nData, sizeof(HEA));
		if (pHea)
		{
			char* pTai = (char*)MemStrX(pHea, (void*)TAI, nData, sizeof(TAI));
			if (pTai)
			{
				char* pBytes = pTai + sizeof(TAI);
				int nBytes = nData - (pBytes - pData);
				memmove(pHea, pBytes, nBytes);
				isSucc = FileUtil::ReadWrite(pszFile, pData, pHea - pData + nBytes, false);
			}
		}
	}
	free(pData);
	CrypUtil::Decrypt(HEA, HEA, sizeof(HEA), 0x5A);
	CrypUtil::Decrypt(TAI, TAI, sizeof(TAI), 0x5A);
	return isSucc;
}

bool SysUtil::IsEnANSI(const char* pszStr)
{
	if (!pszStr) { return false; }

	int i = 0;
	for (;pszStr[i];++i)
	{
		if (pszStr[i] & 0x80) { break; }
	}

	return !pszStr[i];
}
